package com.homedo.odin.solution.service.bizservice.personal;

import com.github.pagehelper.PageInfo;
import com.homedo.core.common.base.dto.Meta;
import com.homedo.core.common.exception.BizException;
import com.homedo.core.common.util.BeanUtils;
import com.homedo.core.common.util.HttpClient;
import com.homedo.core.common.util.ObjectConverter;
import com.homedo.core.common.util.ParamCheckUtil;
import com.homedo.odin.solution.contract.pc.EarningReq;
import com.homedo.odin.solution.contract.pc.GetFreezeReq;
import com.homedo.odin.solution.contract.pc.GetFreezeResp;
import com.homedo.odin.solution.contract.pc.GetProfitReq;
import com.homedo.odin.solution.contract.pc.GetProfitResp;
import com.homedo.odin.solution.contract.pc.PayHebiReq;
import com.homedo.odin.solution.contract.personal.treasure.AddScoreReq;
import com.homedo.odin.solution.contract.personal.userhomepage.AddPopularityReq;
import com.homedo.odin.solution.enumcode.TemplateCodeEnum;
import com.homedo.odin.solution.enumcode.basic.ErrorCodeEnum;
import com.homedo.odin.solution.enumcode.constant.ConstantUtils;
import com.homedo.odin.solution.enumcode.hebi.HebiOrderBizTypeEnum;
import com.homedo.odin.solution.enumcode.hebi.HebiOrderResultStatusEnum;
import com.homedo.odin.solution.enumcode.hebi.HebiOrderStatusEnum;
import com.homedo.odin.solution.enumcode.other.MoneyEnum;
import com.homedo.odin.solution.enumcode.other.PopularityEnum;
import com.homedo.odin.solution.enumcode.other.RemarkEnum;
import com.homedo.odin.solution.enumcode.other.ScoreRuleEnum;
import com.homedo.odin.solution.model.dto.HebiOrderBean;
import com.homedo.odin.solution.model.dto.LevelRule;
import com.homedo.odin.solution.model.dto.PageBean;
import com.homedo.odin.solution.model.dto.ScoreLevelPrivilege;
import com.homedo.odin.solution.model.entity.HebiOrder;
import com.homedo.odin.solution.model.entity.HebiOrderLog;
import com.homedo.odin.solution.model.entity.Message;
import com.homedo.odin.solution.model.entity.MessageType;
import com.homedo.odin.solution.model.entity.Solution;
import com.homedo.odin.solution.model.entity.UserBasic;
import com.homedo.odin.solution.model.entity.UserProfile;
import com.homedo.odin.solution.model.entity.UserScore;
import com.homedo.odin.solution.model.entity.UserScoreDetail;
import com.homedo.odin.solution.service.HebiOrderLogServiceImpl;
import com.homedo.odin.solution.service.HebiOrderServiceImpl;
import com.homedo.odin.solution.service.MessageServiceImpl;
import com.homedo.odin.solution.service.MessageTypeServiceImpl;
import com.homedo.odin.solution.service.ScoreLevelServiceImpl;
import com.homedo.odin.solution.service.SolutionServiceImpl;
import com.homedo.odin.solution.service.UserBasicServiceImpl;
import com.homedo.odin.solution.service.UserPopularityDetailServiceImpl;
import com.homedo.odin.solution.service.UserProfileServiceImpl;
import com.homedo.odin.solution.service.UserScoreDetailServiceImpl;
import com.homedo.odin.solution.service.UserScoreServiceImpl;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.math.BigDecimal;
import java.net.URL;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
import javax.servlet.http.HttpServletResponse;
import net.sf.json.JSONObject;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;

/**
 * @author: donglibing
 * @date: 2018/3/7 18:58
 * @Description: 悬赏业务处理
 */
@Service
public class CommonBizService {


    public static final String SERIAL_NUMBER = "SerialNumber";

    @Autowired
    MessageTypeServiceImpl messageTypeService;

    @Autowired
    MessageServiceImpl messageService;

    @Autowired
    UserBasicServiceImpl userBasicService;

    @Autowired
    SolutionServiceImpl solutionService;

    @Autowired
    HebiOrderServiceImpl hebiOrderService;

    @Autowired
    HebiOrderLogServiceImpl hebiOrderLogService;

    @Autowired
    UserTreasureBizService userTreasureBizService;

    @Autowired
    UserPopularityDetailServiceImpl popularityDetailService;

    @Autowired
    UserProfileServiceImpl userProfileService;

    @Autowired
    UserScoreDetailServiceImpl userScoreDetailService;

    @Autowired
    UserScoreServiceImpl userScoreService;

    @Autowired
    ScoreLevelServiceImpl helper;


    @Value("${Hebi_Host_Url}")
    private String hostUrl;

    @Value("${APPID}")
    private String appId;


    private static final Logger logger = LoggerFactory.getLogger(CommonBizService.class);

    /**
     * 发送信息
     */

    public void sentMessage(Map<String, String> map, int toUser, int fromUser, String Code) {

        if (map == null || map.size() == 0) {
            throw new BizException(Meta.CODE_451.getCode(), Meta.CODE_451.getMsg());
        }
        MessageType messageType = messageTypeService.getMessageTemplate(Code);
        if (messageType == null || messageType.getTemplate() == null) {
            throw new BizException(Meta.CODE_451.getCode(), "未查询到模板，请确认code");
        }
        String message = messageType.getTemplate();
        for (String key : map.keySet()) {
            message = message.replaceAll(key, String.valueOf(map.get(key)));
        }
        Message messageBean = new Message();
        messageBean.setTitle(messageType.getName());
        messageBean.setContent(message);
        messageBean.setToUser(toUser);
        messageBean.setType(Code);
        messageBean.setFromeUser(fromUser);
        boolean result2 = messageService.insert(messageBean);
        if (!result2) {
            throw new BizException(Meta.CODE_500.getCode(), "发送信息异常");
        }
    }

    public UserBasic validationUser(int userId) {
        //判断是否存在该uid
        Map<String, Object> map = new HashMap<>();
        map.put("user_id", userId);
        List<UserBasic> userBasics = userBasicService.selectByMap(map);
        if (userBasics == null || userBasics.size() == 0) {
            throw new BizException(Meta.CODE_451.getCode(), "不存在该用户，请确认userid和username");
        }
        return userBasics.get(0);
    }

    public void downZip(String docUrl, HttpServletResponse response, String fileName) throws Exception {

        try {
            if (docUrl == null || docUrl.length() == 0) {
                throw new BizException(Meta.CODE_451.getCode(), Meta.CODE_451.getMsg());
            }
            //String str=URLEncoder.encode("http://image01.homedo.com/Files/Images/cms/www/20180302/4714509149572946159_pic1.png","utf-8");//编码
            //String str1=URLDecoder.decode(str,"utf-8");//解码
            String[] files = docUrl.split(",");
            for (int i = 0; i < files.length; i++) {
                files[i] = URLDecoder.decode(files[i], "utf-8");
            }

            String downloadFilename = StringUtils.isBlank(fileName) ? "DocumentPackage.zip" : fileName + ".zip";//文件的名称
            downloadFilename = URLEncoder.encode(downloadFilename, "UTF-8");//转换中文否则可能会产生乱码
            response.setContentType("application/octet-stream");// 指明response的返回对象是文件流
            response.setHeader("Content-Disposition", "attachment;filename=" + downloadFilename);// 设置在下载框默认显示的文件名
            ZipOutputStream zos = new ZipOutputStream(response.getOutputStream());
            for (int i = 0; i < files.length; i++) {
                try {
                    URL url = new URL(files[i]);
                    int begin = files[i].lastIndexOf("/");
                    String returnFileName = files[i].substring(begin + 1, files[i].length());
                    zos.putNextEntry(new ZipEntry(returnFileName));

                    InputStream fis = url.openConnection().getInputStream();
                    byte[] buffer = new byte[1024];
                    int r = 0;
                    while ((r = fis.read(buffer)) != -1) {
                        zos.write(buffer, 0, r);
                    }
                    fis.close();
                } catch (Exception ex) {
                    logger.warn("文件无法下载：" + files[i]);
                }

            }
            zos.flush();
            zos.close();
        } catch (UnsupportedEncodingException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }


    }


    /**
     * 河币扣除
     */

    @Transactional(rollbackFor = {RuntimeException.class, Exception.class})
    public void payHebi(PayHebiReq req) {

        //1.数据校验
        if (StringUtils.isEmpty(req.getBizType()) || StringUtils.isEmpty(req.getBizId())
                || req.getHebiAmount().compareTo(new BigDecimal(0)) < 0 || req.getUserId() <= 0
                || req.getDiscountAmount().compareTo(new BigDecimal(0)) < 0) {
            throw new BizException(Meta.CODE_451.getCode(), Meta.CODE_451.getMsg());
        }
        //判断用户是否存在
        validationUser(req.getUserId());
        //方案
        if (HebiOrderBizTypeEnum.SOLUTION.getDbValue().equals(req.getBizType())) {
            paySolution(req);
        }

    }

    /**
     * 方案河币扣除
     */
    public void paySolution(PayHebiReq req) {
        //1.判断bizId是否存在
        Map<String, Object> map = new HashMap<>();
        map.put("is_del", 0);
        map.put("solution_id", req.getBizId());
        List<Solution> solutions = solutionService.selectByMap(map);
        if (solutions == null || solutions.isEmpty()) {
            throw new BizException(Meta.CODE_451.getCode(), "不存在该方案");
        }

        pay(req, MoneyEnum.SolutionDownLoad.getCode(), MoneyEnum.SolutionDownLoad.getMsg());

    }

    private void pay(PayHebiReq req, String usingType, String type) {

        //判断河币金额和打折后的河币金额是否符合要求
        ScoreLevelPrivilege scoreLevelPrivilege = userTreasureBizService.getPrivilegeByUserId(req.getUserId());
        if (scoreLevelPrivilege == null) {
            throw new BizException(Meta.CODE_451.getCode(), "未查询到该会员等级信息");
        }
        if (req.getHebiAmount().compareTo(req.getDiscountAmount()) != 0) {
            throw new BizException(Meta.CODE_451.getCode(), "河币不打折");
        }

        HebiOrder hebiOrder = null;
        HebiOrderBean oldHebiOrder = null;
        String minusUrl = hostUrl + "/IntegralService/Integral/Minus";
        String refundUrl = hostUrl + "/IntegralService/Integral/Refund";

        MultiValueMap<String, String> params = new LinkedMultiValueMap<String, String>();
        params.add("UsingType", usingType);
        params.add("AppId", appId);
        params.add("Type", type);
        params.add("AccountId", String.valueOf(req.getUserId()));
        params.add("Remark", type + "（支出）");

        //2.判断流水订单表该订单是否存在
        Map<String, Object> map1 = new HashMap<>();
        map1.put("is_del", 0);
        map1.put("biz_id", req.getBizId());
        map1.put("user_id", req.getUserId());
        map1.put("biz_type", req.getBizType());
        List<HebiOrder> hebiOrders = hebiOrderService.selectByMap(map1);
        //如果存在该流水订单，修改

        //每次扣减，都需要重新生成uuid
        String uuid = UUID.randomUUID().toString().replaceAll("-", "");
        if (hebiOrders != null && !hebiOrders.isEmpty()) {
            hebiOrder = hebiOrders.get(0);

            //判断是否已经支付完成
            if (hebiOrder.getStatus().equals(HebiOrderStatusEnum.ROLLOUT.getDbValue()) && hebiOrder.getResultStatus()
                    .equals(HebiOrderResultStatusEnum.SUCCESS.getDbValue())) {
                return;
            }

            //判断订单状态，只有冻结和支付失败才可以修改订单的河币金额
            if (!hebiOrder.getStatus().equals(HebiOrderStatusEnum.FREEZE.getDbValue()) && !hebiOrder.getStatus()
                    .equals(HebiOrderStatusEnum.FAIL.getDbValue())) {
                throw new BizException(Meta.CODE_451.getCode(), "订单状态不属于冻结或支付状态，无法修改订单的河币金额");
            }
            oldHebiOrder = ObjectConverter.copyProperties(hebiOrder, HebiOrderBean.class);

            hebiOrder.setHebiAmount(req.getHebiAmount());
            hebiOrder.setDiscountAmount(req.getDiscountAmount());
            hebiOrder.setStatus(HebiOrderStatusEnum.FREEZE.getDbValue());

            BigDecimal amount = req.getDiscountAmount().subtract(oldHebiOrder.getDiscountAmount());
            if (amount.compareTo(new BigDecimal(0)) == 0 && oldHebiOrder.getStatus()
                    .equals(HebiOrderStatusEnum.FREEZE.getDbValue())) {
                //第一种情况 如果当前参数河币的金额等于订单表中的金额 不做任何处理
                return;
            }

            if (HebiOrderResultStatusEnum.FAILURE.getDbValue().equals(oldHebiOrder.getResultStatus())) {
                //如果之前支付失败，则按照传参河币金额
                params.add("Amount", req.getDiscountAmount().toString());

            } else if (amount.compareTo(new BigDecimal(0)) > 0) {
                //第二种情况 如果当前参数河币的金额大于订单表中的金额，进行差额累加
                params.add("Amount", amount.toString());

            } else {
                //第三种情况 如果当前参数河币的金额小于订单表中的金额，先河币返还，然后进行河币扣除
                //1.计入订单流水日志表 返还
                HebiOrderLog hebiOrderLog = ObjectConverter.copyProperties(oldHebiOrder, HebiOrderLog.class);
                hebiOrderLog.setStatus(HebiOrderStatusEnum.RESTITUTION.getDbValue());
                hebiOrderLog.setRemark(RemarkEnum.Restitution.getMsg());
                hebiOrderLog.setCreatedTime(null);
                hebiOrderLog.setModifiedTime(null);
                insertOrderLog(hebiOrderLog);

                //2.计入订单流水日志表 重新扣除河币
                HebiOrderLog newHebiOrderLog = ObjectConverter.copyProperties(hebiOrder, HebiOrderLog.class);
                newHebiOrderLog.setRemark(RemarkEnum.AgainDeduct.getMsg());
                newHebiOrderLog.setCreatedTime(null);
                newHebiOrderLog.setModifiedTime(null);
                insertOrderLog(newHebiOrderLog);

                //3.返还
                MultiValueMap<String, String> refundParams = new LinkedMultiValueMap<String, String>();
                refundParams.add("AppId", appId);
                refundParams.add("SerialNumber", hebiOrder.getUuid());
                refundParams.add("AccountId", String.valueOf(req.getUserId()));
                String reslutJson = HttpClient.post(refundUrl, refundParams);
                JSONObject jsonObject = JSONObject.fromObject(reslutJson);
                if (!(boolean) jsonObject.get(ConstantUtils.HebiConstants.IS_OK)) {
                    throw new BizException(Meta.CODE_500.getCode(), req.getUserId() + "_返还河币失败");
                }
                //4.扣除 设置扣除的河币数
                params.add("Amount", req.getDiscountAmount().toString());
            }

            hebiOrder.setUuid(uuid);

            //更新订单金额
            hebiOrder.setModifiedTime(null);
            boolean result = hebiOrderService.updateById(hebiOrder);
            if (!result) {
                throw new BizException(Meta.CODE_500.getCode(), "更新订单金额失败");
            }

        } else {
            //如果未查询到订单表数据，进行插入操作
            HebiOrder newHebiOrder = new HebiOrder();
            newHebiOrder.setStatus(HebiOrderStatusEnum.FREEZE.getDbValue());

            newHebiOrder.setUuid(uuid);
            newHebiOrder.setModifiedBy(req.getUserId());
            newHebiOrder.setCreatedBy(req.getUserId());
            newHebiOrder.setBizId(req.getBizId());
            newHebiOrder.setUserId(req.getUserId());
            newHebiOrder.setBizType(req.getBizType());
            newHebiOrder.setHebiAmount(req.getHebiAmount());
            newHebiOrder.setDiscountAmount(req.getDiscountAmount());
            newHebiOrder.setResultStatus("success");
            boolean result1 = hebiOrderService.insert(newHebiOrder);
            if (!result1) {
                throw new BizException(Meta.CODE_500.getCode(), req.getUserId() + "_插入订单表数据失败");
            }
            hebiOrder = newHebiOrder;
            //扣除 设置扣除的河币数
            params.add("Amount", req.getDiscountAmount().toString());


        }
        //3.计入订单流水日志表 冻结
        hebiOrder.setStatus(HebiOrderStatusEnum.FREEZE.getDbValue());
        hebiOrder.setResultStatus("success");
        HebiOrderLog hebiOrderLog = ObjectConverter.copyProperties(hebiOrder, HebiOrderLog.class);
        hebiOrderLog.setRemark(RemarkEnum.Freeze.getMsg());
        hebiOrderLog.setModifiedTime(null);
        hebiOrderLog.setCreatedTime(null);
        insertOrderLog(hebiOrderLog);
        if (req.getDiscountAmount().compareTo(new BigDecimal(0)) == 0) {
            return;
        }
        //发送http请求并返回结果 扣除河币
        params.add(SERIAL_NUMBER, uuid);
        String reslutJson = HttpClient.post(minusUrl, params);
        JSONObject jsonObject = JSONObject.fromObject(reslutJson);
        if (!(boolean) jsonObject.get(ConstantUtils.HebiConstants.IS_OK)) {
            //如果失败，更新订单状态
            hebiOrder.setResultStatus("failure");
            hebiOrderService.updateById(hebiOrder);
            //如果失败，更新刚插入的log状态
            hebiOrderLog.setResultStatus("failure");
            hebiOrderLogService.updateById(hebiOrderLog);
            //throw new BizException(Meta.CODE_500.getDbValue(), "扣除河币*失败");
        }

    }

    /**
     * 插入订单流水日志表
     */
    private void insertOrderLog(HebiOrderLog hebiOrderLog) {
        boolean re = hebiOrderLogService.insert(hebiOrderLog);
        if (!re) {
            throw new BizException(Meta.CODE_500.getCode(), hebiOrderLog.getRemark() + "失败");
        }
    }

    /**
     * 河币转入，并修改订单状态
     */
    @Transactional(rollbackFor = {RuntimeException.class, Exception.class})
    public void earning(EarningReq req) {
        //1.数据校验
        if (StringUtils.isEmpty(req.getBizType()) || StringUtils.isEmpty(req.getBizId())
                || req.getHebiAmount().compareTo(new BigDecimal(0)) < 0 || req.getUserId() <= 0
                || req.getPublishUserId() <= 0) {
            throw new BizException(Meta.CODE_451.getCode(), Meta.CODE_451.getMsg());
        }
        //判断用户是否存在
        validationUser(req.getUserId());
        validationUser(req.getPublishUserId());
        //方案
        if (req.getBizType().equals(HebiOrderBizTypeEnum.SOLUTION.getDbValue())) {
            HebiOrder hebiOrder = getHebiOrder(req.getBizId(), req.getUserId(), req.getPublishUserId(),
                    req.getBizType());
            solutionEarningHebi(req, hebiOrder);

        } else {
            throw new BizException(Meta.CODE_451.getCode(), Meta.CODE_451.getMsg());
        }

    }


    /**
     * 获取河币订单信息
     */
    private HebiOrder getHebiOrder(String bizId, int userId, int publisherUserId, String bizType) {

        //1.判断bizId是否存在
        Map<String, Object> map = new HashMap<>();
        map.put("is_del", 0);
        map.put("solution_id", bizId);
        map.put("user_id", publisherUserId);
        List<Solution> solutions = solutionService.selectByMap(map);
        if (solutions == null || solutions.size() == 0) {
            throw new BizException(Meta.CODE_451.getCode(), "不存在该方案");
        }
        //2.判断流水订单表该订单是否存在
        Map<String, Object> map1 = new HashMap<>();
        map1.put("is_del", 0);
        map1.put("biz_id", bizId);
        map1.put("user_id", userId);
        map1.put("biz_type", bizType);
        List<HebiOrder> hebiOrders = hebiOrderService.selectByMap(map1);
        if (hebiOrders == null || hebiOrders.size() == 0) {
            throw new BizException(Meta.CODE_451.getCode(), "不存在该流水订单");
        }
        //3.判断该订单是否已经支付过了
        Map<String, Object> map2 = new HashMap<>();
        map2.put("is_del", 0);
        map2.put("biz_id", bizId);
        map2.put("user_id", userId);
        map2.put("biz_type", bizType);
        map2.put("result_status", HebiOrderResultStatusEnum.SUCCESS.getDbValue());
        map2.put("status", HebiOrderStatusEnum.ROLLOUT.getDbValue());
        List<HebiOrder> hebiOrders1 = hebiOrderService.selectByMap(map2);
        if (hebiOrders1 != null && hebiOrders1.size() > 0) {
            throw new BizException(Meta.CODE_451.getCode(), "该订单已存在，无需重复支付");
        }

        HebiOrder hebiOrder = hebiOrders.get(0);
        return hebiOrder;
    }

    /**
     * 河币转入
     */
    public void solutionEarningHebi(EarningReq req, HebiOrder hebiOrder) {

        String uuid = UUID.randomUUID().toString().replaceAll("-", "");

        //先判断订单表里支付存在该订单记录
        Map<String, Object> map = new HashMap<>();
        map.put("biz_id", req.getBizId());
        map.put("user_id", req.getPublishUserId());
        map.put("biz_type", req.getBizType());
        map.put("status", HebiOrderStatusEnum.PROFIT.getDbValue());
        map.put("from_user_id", req.getUserId());
        List<HebiOrder> hebiOrders = hebiOrderService.selectByMap(map);
        HebiOrder newPublishOrder = null;
        if (hebiOrders != null && hebiOrders.size() > 0) {
            HebiOrder oldProfitHebiOrder = hebiOrders.get(0);
            if (HebiOrderResultStatusEnum.SUCCESS.getDbValue().equals(oldProfitHebiOrder.getResultStatus())) {
                throw new BizException(Meta.CODE_451.getCode(), "该下载者已经支付过订单并且成功转入到发布者账户中，无需重复扣除河币");
            }
            oldProfitHebiOrder.setResultStatus(HebiOrderResultStatusEnum.SUCCESS.getDbValue());
            hebiOrderService.updateById(oldProfitHebiOrder);
            newPublishOrder = oldProfitHebiOrder;
        } else {
            //3.插入发布者的订单流水
            newPublishOrder = new HebiOrder();
            newPublishOrder.setStatus(HebiOrderStatusEnum.PROFIT.getDbValue());
            newPublishOrder.setHebiAmount(req.getHebiAmount());
            newPublishOrder.setUserId(req.getPublishUserId());
            newPublishOrder.setCreatedBy(req.getPublishUserId());
            newPublishOrder.setModifiedBy(req.getPublishUserId());
            newPublishOrder.setUuid(uuid);
            newPublishOrder.setResultStatus(HebiOrderResultStatusEnum.SUCCESS.getDbValue());
            newPublishOrder.setFromUserId(req.getUserId());
            newPublishOrder.setBizId(req.getBizId());
            newPublishOrder.setBizType(HebiOrderBizTypeEnum.SOLUTION.getDbValue());
            newPublishOrder.setDiscountAmount(req.getHebiAmount());
            boolean result = hebiOrderService.insert(newPublishOrder);
            if (!result) {
                throw new BizException(Meta.CODE_500.getCode(), "插入发布者订单流水失败");
            }
        }

        //计入发布者的订单流水日志
        HebiOrderLog hebiOrderLog = ObjectConverter.copyProperties(newPublishOrder, HebiOrderLog.class);
        hebiOrderLog.setRemark(RemarkEnum.Profit.getMsg());
        insertOrderLog(hebiOrderLog);

        //4.更新下载者的订单流水状态
        hebiOrder.setStatus(HebiOrderStatusEnum.ROLLOUT.getDbValue());
        hebiOrder.setResultStatus(HebiOrderResultStatusEnum.SUCCESS.getDbValue());
        boolean result1 = hebiOrderService.updateById(hebiOrder);
        if (!result1) {
            throw new BizException(Meta.CODE_500.getCode(), "更新下载者订单流水失败");
        }

        //计入下载者的订单流水日志
        HebiOrderLog downLog = ObjectConverter.copyProperties(hebiOrder, HebiOrderLog.class);
        downLog.setRemark(RemarkEnum.PayComplete.getMsg());
        downLog.setCreatedTime(null);
        downLog.setModifiedTime(null);
        insertOrderLog(downLog);

        //6.河币转入到方案发布者账户
        String url = hostUrl + "/IntegralService/Integral/Add";

        //post请求
        MultiValueMap<String, String> params = new LinkedMultiValueMap<>();
        params.add("AppId", appId);
        params.add("CashEnable", "false");
        params.add("SerialNumber", uuid);
        params.add("Type", MoneyEnum.Solutionprofit.getMsg());
        params.add("Amount", String.valueOf(req.getHebiAmount()));
        params.add("AccountId", String.valueOf(req.getPublishUserId()));
        params.add("Remark", "方案分成河币(收入)");
        //发送http请求并返回结果
        String reslutJson = HttpClient.post(url, params);
        JSONObject jsonObject = JSONObject.fromObject(reslutJson);
        if (!(boolean) jsonObject.get(ConstantUtils.HebiConstants.IS_OK)) {
            //更新发布者的订单状态和日志记录未failure
            newPublishOrder.setResultStatus(HebiOrderResultStatusEnum.FAILURE.getDbValue());
            hebiOrderService.updateById(newPublishOrder);
            hebiOrderLog.setResultStatus(HebiOrderResultStatusEnum.FAILURE.getDbValue());
            hebiOrderLogService.updateById(hebiOrderLog);

            //更新下载者的订单状态和日志记录为failure
            hebiOrder.setResultStatus(HebiOrderResultStatusEnum.FAILURE.getDbValue());
            hebiOrderService.updateById(hebiOrder);
            downLog.setResultStatus(HebiOrderResultStatusEnum.FAILURE.getDbValue());
            hebiOrderLogService.updateById(downLog);
            //callBackFailSolutionOrder(req,hebiOrder);
            //throw new BizTSException(Meta.CODE_500.getDbValue(), "河币转入到方案发布者失败");
        }

    }

    /**
     * 根据userId获取收益列表
     */
    public GetProfitResp getProfitList(GetProfitReq req) {
        GetProfitResp resp = new GetProfitResp();
        PageBean pageBean = new PageBean(req.getPageNum(), req.getPageSize());
        PageInfo<HebiOrder> profitList = hebiOrderService
                .getProfitList(pageBean, req.getUserId(), req.getBizId(), req.getBizType());
        resp = BeanUtils.transfrom(GetProfitResp.class, profitList);

        HebiOrder hb = hebiOrderService.getProfitAmount(req.getUserId());
        resp.setTotalAmount(hb.getDiscountAmount());
        return resp;
    }

    /**
     * 获取冻结订单
     */
    public GetFreezeResp getFreeze(GetFreezeReq req) {
        GetFreezeResp resp = new GetFreezeResp();
        //验证用户id
        if (StringUtils.isEmpty(req.getBizId()) || req.getUserId() < 0 || StringUtils.isEmpty(req.getBizType())) {
            throw new BizException(Meta.CODE_451.getCode(), Meta.CODE_451.getMsg());
        }
        validationUser(req.getUserId());
        Map<String, Object> map = new HashMap<>();
        map.put("biz_id", req.getBizId());
        map.put("biz_type", req.getBizType());
        map.put("is_del", 0);
        map.put("user_id", req.getUserId());
        List<HebiOrder> hebiOrders = hebiOrderService.selectByMap(map);
        if (hebiOrders == null || hebiOrders.size() == 0) {
            throw new BizException(Meta.CODE_451.getCode(), "不存在该订单");
        }
        HebiOrder hebiOrder = hebiOrders.get(0);
        HebiOrderBean hebiOrderBean = ObjectConverter.copyProperties(hebiOrder, HebiOrderBean.class);
        resp.setHebiOrder(hebiOrderBean);
        return resp;
    }

    /**
     * 新增人气值
     */
    @Transactional(rollbackFor = {Exception.class, RuntimeException.class})
    public void addPopularity(AddPopularityReq req) {
        logger.info("新增人气值请求参数:{}", req.toJson());
        if (req.getTargetId() == null || req.getTargetId() <= 0) {
            logger.info("目标用户id不合规");
            throw new BizException(Meta.CODE_451.getCode(), "目标用户id不合规");
        }
        if (req.getType() == null) {
            logger.info("人气值类型不能为空");
            throw new BizException(Meta.CODE_451.getCode(), "人气值类型不能为空");
        }
        if (req.getOperationId().equals(req.getTargetId())) {
            //自己操作不增加人气值
            logger.info("自己操作不增加人气值");
            return;
        }
        PopularityEnum popularityEnum = PopularityEnum.getPopularityEnum(req.getType());
        //插入人气明细表
        popularityDetailService
                .insert(req.getOperationId(), req.getTargetId(), req.getType(), popularityEnum.getScore());
        //更新主页人气值
        userProfileService.updateClickCount(req.getTargetId(), req.getOperationId(), popularityEnum.getScore());
    }


    /**
     * 增加积分，提升等级
     */
    @Transactional(rollbackFor = {Exception.class, RuntimeException.class})
    public void addScore(AddScoreReq request) {
        logger.info("增加积分请求参数:{}", request.toJson());
        Integer userId = request.getUserId();
        Integer type = request.getType();
        ParamCheckUtil.checkUserId(userId);
        if (type == null) {
            logger.info("积分类型不能为空");
            throw new BizException(Meta.CODE_451.getCode(), "积分类型不能为空");
        }
        UserBasic userBasic = userBasicService.selectByUserId(userId);
        if (userBasic == null) {
            logger.info("不存在该用户，请确认userId");
            throw new BizException(Meta.CODE_451.getCode(), "不存在该用户，请确认userId");
        }
        ScoreRuleEnum ruleEnum = ScoreRuleEnum.getScoreRuleEnum(type);
        //判断该积分类型是不是已经达到上限
        Integer count = userScoreDetailService.selectCountByTypeAndUserId(userId, ruleEnum.getType());
        if (count >= ruleEnum.getLimit()) {
            //已经达到或超过上限，直接返回
            logger.info("用户获取积分已达到上限，获取方式：{},userId:{}", ruleEnum.getType(), userId);
            return;
        }
        if (type.equals(ScoreRuleEnum.SingIn.getType())) {
            //如果签到，需要判断当天是否已签到
            UserScoreDetail detail = userScoreDetailService.findByTodaySingIn(type, userId);
            if (detail != null) {
                //已经签到
                logger.info("用户重复签到，userId:{}", userId);
                throw new BizException(ErrorCodeEnum.IsExist.getDbValue(), "重复签到");
            }
        }
        //在积分详情表中插入数据
        userScoreDetailService.insert(userId, type, ruleEnum.getScore(), request.getBizCode());
        //获取用户当前积分，并更新
        UserScore userScore = userScoreService.selectByUserId(userId);
        if (userScore == null) {
            //第一次使用，新增积分数据
            userScore = new UserScore();
            userScore.setScoreLevel(1);
            userScore.setTotal(ruleEnum.getScore());
            userScore.setUserId(userId);
            userScore.setModifiedBy(userId);
            userScore.setCreatedBy(userId);
            userScoreService.insert(userScore);
            return;
        }
        //已有积分数据,更新积分并需要判断是否升级
        Integer currentLevel = userScore.getScoreLevel();
        Integer score = userScore.getTotal() + ruleEnum.getScore();
        LevelRule level = helper.getScoreLevelByScore(score);
        userScore.setTotal(score);
        userScore.setScoreLevel(level.getLevel());
        userScore.setModifiedTime(new Date());
        userScoreService.updateById(userScore);
        //用户达到二级，新建用户主页
        if (currentLevel != 2 && level.getLevel() == 2) {
            logger.info("新建用户主页！userId:{}", userId);
            UserProfile profile = userProfileService.selectByUserId(userId);
            if (profile == null) {
                profile = new UserProfile();
            }
            profile.setUserId(userId);
            profile.setModifiedBy(userId);
            profile.setCreatedBy(userId);
            //获取人气值
            Integer clickCount = popularityDetailService.selectScoreCountByUserId(userId);
            profile.setClickCount(clickCount);
            profile.setModifiedTime(new Date());
            userProfileService.insertOrUpdate(profile);
        }
        //用户升级，发送消息
        if (level.getLevel() > currentLevel) {
            logger.info("用户升级了！userId:{}", userId);
            Map<String, String> map = new HashMap<>();
            map.put("@@userName",
                    StringUtils.isBlank(userBasic.getNickName()) ? userBasic.getUserName() : userBasic.getNickName());
            map.put("@@levelName", level.getLevelName());
            map.put("@@count", score.toString());
            sentMessage(map, userId, 0, TemplateCodeEnum.level_up.toString());
        }
    }

}
